dbt-datamocktoolを使ってテスト用の入出力ファイルを用いたモデルのロジックテストをしてみた
データアナリティクス事業本部のueharaです。
今回は、dbt-datamocktoolを使ってテスト用の入出力ファイル(csv)を用いたモデルのロジックテストをしてみたいと思います。
はじめに
dbtで標準で備わっているテスト機能は、ユニーク性やバリデーションといったデータそのものの品質をテストするのが主な目的であるため、基本的にはモデルのロジックをテストする際には別のパッケージが必要になります。
その中でも、今回はdbt-datamocktoolを利用してみたいと思います。
【2023/12/18 追記】
dbt-core v1.8
から単体テストが標準機能で提供されるようです。
Discussionsを眺めていると、csvファイルを使ったテストにも対応しているようです。
ディレクトリ構成
必要な部分だけ記載しますが、今回のディレクトリ構成は以下の通りです。
dbt_dev ├ models | ├ dev | | ├ my_model.sql # 今回テスト対象のモデル | | └ schema.yml | └ raw.yml # sourceを記載 ├ seeds | └ test_data | ├ test__expected_output.csv # 今回のテスト用入力ファイル | └ test__raw_input.csv # 今回のテスト用期待値の出力ファイル ├ dbt_project.yml └ package.yml
package.yml
package.ymlには、依存パッケージとして今回利用する dbt_datamocktool
を記載します。
packages: - package: mjirv/dbt_datamocktool version: 0.3.5
dbt_project.yml
dbt_project.ymlは以下です。
version: '1.0.0' config-version: 2 profile: 'dbt_dev' model-paths: ["models"] analysis-paths: ["analyses"] test-paths: ["tests"] seed-paths: ["seeds"] macro-paths: ["macros"] snapshot-paths: ["snapshots"] clean-targets: - "target" - "dbt_packages" seeds: dbt_dev: test_data: +schema: test models: dbt_dev: dev: +materialized: table
dbt seed
によってロードされる際、 test_data
フォルダ以下のデータは test
というカスタムスキーマでロードされるよう指定しています。
今回は target: dev
に対して dev
というスキーマを利用することを想定しているため、テストデータは dev_test
というスキーマ配下にロードされることになります。
raw.yml
raw.ymlは以下です。
raw
スキーマ配下に raw_input
というテーブルがあることを想定します。
version: 2 sources: - name: staging database: dbt_dev schema: raw tables: - name: raw_input
my_model.sql
今回のテスト対象のモデル my_model は、あまり面白くは無いですが以下のようにしてみました。
select id, data * 5 as data from {{ source('staging', 'raw_input') }}
raw_input
テーブルから id
と data
を取得し、 data
に関してはその値を5倍にしています。
schema.yml
schema.ymlは以下です。
version: 2 models: - name: my_model tests: - dbt_datamocktool.unit_test: input_mapping: source('staging', 'raw_input'): ref('test__raw_input') expected_output: ref('test__expected_output')
my_model に対し、dbt_datamocktool
でのロジックテストを記載しています。
設定値に関しては、元のsourceのデータにテストデータである ref('test__raw_input')
をマッピングし、期待する出力を指定しています。
テストデータのcsvファイル
入力と期待する出力のcsvファイルはそれぞれ以下の通りです。
id,data 1,10 2,20 3,30
id,data 1,50 2,100 3,150
先のロジックに従い、入力の data
カラムに対し、出力の data
カラムの値を5倍にしています。
実行確認
まず、依存パッケージのダウンロードのため以下のコマンドを実行します。
$ dbt deps
ダウンロードが完了したら、次にseedコマンドによりテストデータのロードを行います。
$ dbt seed
成功すると、以下の通り dev_test
スキーマ配下にテストに利用するテーブルが作成されているかと思います。
ここまで準備ができたら、テストを実行してみます。
$ dbt test ... 09:18:06 1 of 1 START test dbt_datamocktool_unit_test_my_model_ref_test__expected_output___ref_test__raw_input_ [RUN] 09:18:06 1 of 1 PASS dbt_datamocktool_unit_test_my_model_ref_test__expected_output___ref_test__raw_input_ [PASS in 0.18s] 09:18:06 09:18:06 Finished running 1 test in 0 hours 0 minutes and 0.28 seconds (0.28s). 09:18:06 09:18:06 Completed successfully 09:18:06 09:18:06 Done. PASS=1 WARN=0 ERROR=0 SKIP=0 TOTAL=1
無事、入力とそれに対する期待値のテストデータを用いてテストがPASSできたことが分かります。
逆に、今度はあえてmy_modelの定義を変えて一部データがテスト結果と一致しないようにしてみます。
select id, case id when 3 then data * 2 else data * 5 end as data from {{ source('staging', 'raw_input') }}
上記は id
カラムが3の時だけ data
を5倍ではなく2倍にしています。
これで dbt test
を実行すると、以下の通りエラーが出力されます。
$ dbt test ... 14:04:10 1 of 1 START test dbt_datamocktool_unit_test_my_model_ref_test__expected_output___ref_test__raw_input_ [RUN] 14:04:10 The test <> failed with the differences: 14:04:10 ================================================================ | id | data | in_a | in_b | | -- | ---- | ----- | ----- | | 3 | 150 | True | False | | 3 | 60 | False | True | 14:04:10 ================================================================ 14:04:10 1 of 1 FAIL 2 dbt_datamocktool_unit_test_my_model_ref_test__expected_output___ref_test__raw_input_ [FAIL 2 in 0.09s] 14:04:10 14:04:10 Finished running 1 test in 0 hours 0 minutes and 0.17 seconds (0.17s). 14:04:10 14:04:10 Completed with 1 error and 0 warnings: 14:04:10 14:04:10 Failure in test dbt_datamocktool_unit_test_my_model_ref_test__expected_output___ref_test__raw_input_ (models/dev/schema.yml) 14:04:10 Got 2 results, configured to fail if != 0 14:04:10 14:04:10 compiled Code at target/compiled/dbt_dev/models/dev/schema.yml/dbt_datamocktool_unit_test_my__ef049f60d2b7d5691e3da4484cbbf0e4.sql 14:04:10 14:04:10 Done. PASS=0 WARN=0 ERROR=1 SKIP=0 TOTAL=1
id=3
のデータが期待値と一致していないことが読み取れます。
最後に
今回は、dbt-datamocktoolを使ってテスト用の入出力ファイル(csv)を用いたモデルのロジックテストをしてみました。
参考になりましたら幸いです。